import 'package:dio/dio.dart';

import 'result.dart';

/// 数据初步处理
class ResponseInterceptor extends Interceptor {
  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    final contentType = response.requestOptions.contentType;

    NetworkResult result;

    if (contentType != null && contentType.contains("text")) {
      final data = response.data;
      if (data is Map<String, dynamic>) {
        result = NetworkResult.success(data: data);
      } else {
        result = NetworkResult.failedWithMsg('数据格式错误');
      }
      response.data = result;
      return handler.next(response);
    }

    final statusCode = response.statusCode ?? "-1";

    if (statusCode != 200 && statusCode != 201) {
      response.data = NetworkResult.failed(
        code: '${statusCode}',
        msg: '网络错误',
      );
      return handler.next(response);
    }

    final data = response.data;

    if (data is Map<String, dynamic>) {
      int code = data.intValue('code') ?? -1;
      String msg = data.stringValue('msg') ?? '数据格式错误';
      final mapData = data['data'];

      if (code == 200) {
        if (mapData is Map<String, dynamic>) {
          result = NetworkResult.success(data: mapData, origin: data);
        } else {
          result = NetworkResult.success(data: null, origin: data);
        }
      } else {
        result = NetworkResult.failed(code: '${code}', msg: msg, origin: data);
      }
    } else {
      result = NetworkResult.failedWithMsg('数据格式错误');
    }

    response.data = result;
    return handler.next(response);
  }
}

extension MapReading<K, V> on Map<K, V> {
  /// 如果 value 存在且为 num 或可转换为 num，则返回 num 值；否则返回 null。
  num? numValue(K key) {
    final value = this[key];

    if (value != null) {
      if (value is num) {
        return value;
      } else if (value is String) {
        return num.tryParse(value);
      }
    }

    return null;
  }

  int? intValue(K key) => numValue(key)?.toInt();

  /// 获取 key 对应的字符串值。
  ///
  /// [nullForEmpty] 为 true 时，如果 value 为空字符串，则返回 null。
  String? stringValue(
    K key, {
    bool? nullForEmpty,
  }) {
    final value = this[key];

    if (value != null) {
      if (value is String) {
        if (nullForEmpty ?? false) {
          return value.isEmpty ? null : value;
        }
        return value;
      } else if (value is num) {
        return value.toString();
      }
    }

    return null;
  }
}
